import json
import multiprocessing
import os
import sys
import time
import traceback
from datetime import datetime
from datetime import timedelta
from pathlib import Path

from PySide6.QtCore import QMimeData
from PySide6.QtCore import Qt
from PySide6.QtCore import QThread
from PySide6.QtCore import QUrl
from PySide6.QtCore import Signal
from PySide6.QtGui import QDrag
from PySide6.QtGui import QPixmap
from PySide6.QtGui import QTextCursor
from PySide6.QtWidgets import QApplication
from PySide6.QtWidgets import QCheckBox
from PySide6.QtWidgets import QComboBox
from PySide6.QtWidgets import QDialog
from PySide6.QtWidgets import QFileDialog
from PySide6.QtWidgets import QFormLayout
from PySide6.QtWidgets import QGroupBox
from PySide6.QtWidgets import QHBoxLayout
from PySide6.QtWidgets import QLabel
from PySide6.QtWidgets import QLineEdit
from PySide6.QtWidgets import QMainWindow
from PySide6.QtWidgets import QMessageBox
from PySide6.QtWidgets import QPushButton
from PySide6.QtWidgets import QSpinBox
from PySide6.QtWidgets import QSplitter
from PySide6.QtWidgets import QTabWidget
from PySide6.QtWidgets import QTextEdit
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtWidgets import QWidget

from app_config import AppConfig
from capcut_subtitile import convert_json_to_subtitle
from common import clear_audio_temp_dir
from common import get_base_dir
from common import get_temp_path

# 导入现有脚本的功能
from hotkey_agent import HotkeyAgent
from llm import call_llm
from llm import gen_youhua_prompt
from log_manager import LogManager
from split_text import format_time
from split_text import OriginalVideo
from split_text import split_text_by_max_length


def hotkey_agent_start(selected_type, queue):
    hotkey_agent = HotkeyAgent()
    LogManager.set_log_widget(ProcessLogWidget(queue))
    hotkey_agent.start_listen(selected_type)


class LogWidget(QTextEdit):
    """日志输出窗口"""

    log_signal = Signal(str, str)  # 将Signal定义为类属性

    def __init__(self):
        super().__init__()
        self.setReadOnly(True)
        self.setMaximumHeight(150)  # 设置最大高度
        self.log_signal.connect(self.do_log)

    def log(self, message, end="\n"):
        self.log_signal.emit(message, end)

    def do_log(self, message, end="\n"):
        """添加日志"""
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        try:
            if end == "\n":
                self.append(f"[{current_time}] {message}")
            else:
                self.moveCursor(QTextCursor.End)
                self.insertPlainText(message)
            # 滚动到底部
            self.verticalScrollBar().setValue(self.verticalScrollBar().maximum())
        except Exception as e:
            print(f"错误：{str(e)}")


class LogWorker(QThread):

    def __init__(self, queue):
        super().__init__()
        self.queue = queue

    def run(self):
        while True:
            message, end = self.queue.get()
            LogManager.log(message, end)


class ProcessLogWidget(object):
    def __init__(self, queue):
        self.queue = queue

    def log(self, message, end="\n"):
        self.queue.put((message, end))


class YouhuaWorker(QThread):
    finished = Signal(str)  # 完成信号，传递优化后的文案
    error = Signal(str)  # 错误信号，传递错误信息

    def __init__(self, text):
        super().__init__()
        self.text = text

    def run(self):
        try:
            system_prompt, user_prompt = gen_youhua_prompt(self.text)
            content = call_llm(system_prompt, user_prompt)
            self.finished.emit(content)
        except Exception as e:
            self.error.emit(str(e))


class DraggableLabel(QLabel):
    """可拖拽的标签"""

    def __init__(self, file_path, parent=None):
        super().__init__(parent)
        self.file_path = file_path
        self.setPixmap(
            QPixmap(os.path.join(get_base_dir(), "res", "file_icon.png"))
        )  # 需要一个文件图标
        self.setToolTip(f"拖拽到其他应用\n{file_path}")
        self.setCursor(Qt.OpenHandCursor)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drag_start_position = event.pos()

    def mouseMoveEvent(self, event):
        if not (event.buttons() & Qt.LeftButton):
            return

        # 创建拖拽对象
        drag = QDrag(self)
        mime_data = QMimeData()

        # 设置文件URL
        url = QUrl.fromLocalFile(self.file_path)
        mime_data.setUrls([url])

        drag.setMimeData(mime_data)

        # 设置拖拽时的图标
        drag.setPixmap(self.pixmap())

        # 获取主窗口并最小化
        main_window = self.window()
        if main_window:
            main_window.showMinimized()

        # 执行拖拽
        drag.exec_(Qt.CopyAction)


class CapcutExportWorker(QThread):
    """CapCut 字幕导出工作线程"""

    finished = Signal(list)  # 完成信号，传递导出的文件列表
    error = Signal(str)  # 错误信号，传递错误信息

    def __init__(self, project_path, save_path, export_type):
        super().__init__()
        self.project_path = project_path
        self.save_path = save_path
        self.export_type = export_type

    def run(self):
        try:
            # 读取项目文件
            if not self.project_path or not os.path.exists(
                self.project_path / "draft_info.json"
            ):
                raise Exception("项目文件不存在")

            # 读取 JSON 文件，指定编码为 utf-8
            with open(
                self.project_path / "draft_info.json", "r", encoding="utf-8"
            ) as f:
                json_data = json.load(f)

            # 转换字幕
            subtitle_files = convert_json_to_subtitle(json_data, self.export_type)

            # 确保输出目录存在
            os.makedirs(self.save_path, exist_ok=True)

            # 保存文件
            result = []
            for track_id, content in subtitle_files.items():
                output_file = os.path.join(
                    self.save_path,
                    f"{self.project_path.name}_{track_id}.{self.export_type}",
                )
                with open(output_file, "w", encoding="utf-8") as f:
                    f.write(content)
                result.append(output_file)

            self.finished.emit(result)
        except Exception as e:
            self.error.emit(str(e))


class CapcutCheckWorker(QThread):
    """CapCut 字幕校验工作线程"""

    finished = Signal(str)  # 完成信号，传递输出文件路径
    error = Signal(str)  # 错误信号，传递错误信息

    def __init__(self, project_path, save_path, ref_path=None):
        super().__init__()
        self.project_path = project_path
        self.save_path = save_path
        self.ref_path = ref_path

    def run(self):
        try:
            # 检查项目路径
            if not self.project_path or not os.path.exists(
                self.project_path / "draft_info.json"
            ):
                raise Exception("项目文件不存在")

            # 确保输出目录存在
            os.makedirs(self.save_path, exist_ok=True)

            # 读取项目文件
            with open(
                self.project_path / "draft_info.json", "r", encoding="utf-8"
            ) as f:
                json_data = json.load(f)

            # 转换字幕
            subtitle_files = convert_json_to_subtitle(json_data, "srt")

            if not subtitle_files:
                raise Exception("未找到字幕内容")

            # 保存 srt 文件
            srt_file = os.path.join(
                self.save_path, f"{self.project_path.name}_check_temp.srt"
            )

            # 保存第一个字幕轨道
            track_id = list(subtitle_files.keys())[0]
            with open(srt_file, "w", encoding="utf-8") as f:
                f.write(subtitle_files[track_id])

            # 生成输出文件路径
            output = srt_file.rsplit(".", 1)[0] + "_checked.srt"

            # 导入字幕校验功能
            from subtitle_check import check_subtitles

            check_subtitles(srt_file, output, self.ref_path)

            # 清理临时文件
            try:
                os.remove(srt_file)
            except Exception as e:
                LogManager.log(f"错误：{str(e)}")

            self.finished.emit(output)
        except Exception as e:
            self.error.emit(str(e))


class SettingsDialog(QDialog):
    """设置窗口"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.app_config = AppConfig()
        self.setWindowTitle("设置")
        self.setFixedSize(600, 350)  # 增加窗口尺寸
        self.setStyleSheet(
            """
            QDialog {
                background-color: #FFFFFF;
            }
            QGroupBox {
                font-weight: bold;
                border: 1px solid #CCCCCC;
                border-radius: 6px;
                margin-top: 12px;
                padding-top: 12px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 5px;
            }
            QLabel {
                color: #333333;
            }
            QLineEdit {
                padding: 8px;
                border: 1px solid #CCCCCC;
                border-radius: 4px;
                background-color: #FFFFFF;
                selection-background-color: #4A90E2;
                min-width: 400px;  # 增加输入框宽度
                min-height: 36px;  # 设置输入框高度
            }
            QLineEdit:focus {
                border: 1px solid #4A90E2;
            }
            QFormLayout {
                spacing: 20px;  # 增加表单间距
            }
        """
        )

        layout = QVBoxLayout(self)
        layout.setContentsMargins(30, 30, 30, 30)  # 增加边距
        layout.setSpacing(25)  # 增加间距

        # API 设置组
        api_group = QGroupBox("API 设置")
        api_layout = QFormLayout(api_group)
        api_layout.setContentsMargins(25, 30, 25, 25)  # 增加内边距
        api_layout.setSpacing(20)  # 增加间距
        api_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        api_layout.setLabelAlignment(Qt.AlignRight)

        # Base URL 输入框
        self.base_url = QLineEdit()
        self.base_url.setPlaceholderText("请输入 API 基础 URL")
        self.base_url.setMinimumWidth(400)  # 增加最小宽度
        self.base_url.textChanged.connect(self.save_settings)  # 添加自动保存
        api_layout.addRow(self.create_label("Base URL:"), self.base_url)

        # API Key 输入框
        self.api_key = QLineEdit()
        self.api_key.setPlaceholderText("请输入 API Key")
        self.api_key.setEchoMode(QLineEdit.Password)
        self.api_key.setMinimumWidth(400)  # 增加最小宽度
        self.api_key.textChanged.connect(self.save_settings)  # 添加自动保存
        api_layout.addRow(self.create_label("API Key:"), self.api_key)

        # Model 输入框
        self.model = QLineEdit()
        self.model.setPlaceholderText("请输入模型名称")
        self.model.setMinimumWidth(400)  # 增加最小宽度
        self.model.textChanged.connect(self.save_settings)  # 添加自动保存
        api_layout.addRow(self.create_label("Model:"), self.model)

        layout.addWidget(api_group)

        # 提示信息
        tip_label = QLabel("提示：设置内容会自动保存")
        tip_label.setStyleSheet("color: #666666; font-size: 12px;")
        tip_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(tip_label)

        # 加载当前配置
        self.load_settings()

        # 添加伸缩项
        layout.addStretch()

    def create_label(self, text):
        """创建统一样式的标签"""
        label = QLabel(text)
        label.setStyleSheet(
            """
            QLabel {
                font-size: 14px;  # 增加字体大小
                min-width: 100px;  # 增加标签宽度
                padding-right: 15px;  # 增加右边距
            }
        """
        )
        return label

    def load_settings(self):
        """加载当前配置"""
        try:
            self.api_key.setText(self.app_config["api_key"])
            self.base_url.setText(self.app_config["base_url"])
            self.model.setText(self.app_config["model"])
        except Exception as e:
            LogManager.log(f"加载配置失败：{str(e)}")

    def save_settings(self):
        """保存配置"""
        try:
            # 获取当前输入值
            base_url = self.base_url.text().strip()
            api_key = self.api_key.text().strip()
            model = self.model.text().strip()

            # 只有当所有必填字段都有值时才保存
            if base_url and api_key and model:
                self.app_config["api_key"] = api_key
                self.app_config["base_url"] = base_url
                self.app_config["model"] = model

                # 保存到配置文件
                self.app_config.save_config()
                self.log("配置已自动保存")
        except Exception as e:
            self.log(f"保存配置失败：{str(e)}")
            self.show_error(f"保存失败：{str(e)}")

    def show_error(self, message):
        """显示错误消息"""
        from PySide6.QtWidgets import QMessageBox

        QMessageBox.warning(self, "错误", message, QMessageBox.Ok)


class SubtitleWorker(QThread):
    """字幕生成工作线程"""

    finished = Signal(str)  # 完成信号，传递输出文件路径
    error = Signal(str)  # 错误信号，传递错误信息
    progress = Signal(str)  # 进度信号，传递进度信息
    update_output_path = Signal(str)  # 更新输出文件路径信号

    def __init__(
        self,
        video_path,
        output_path,
        ref_path=None,
        is_resolve_mode=False,
        audio_type="local",
        model_name="small",
    ):
        super().__init__()
        self.video_path = video_path
        self.output_path = output_path
        self.ref_path = ref_path
        self.is_resolve_mode = is_resolve_mode
        self.audio_type = audio_type
        self.model_name = model_name

    def run(self):
        try:
            from subtitle_agent import do_task

            self.progress.emit("开始生成字幕...")
            if self.is_resolve_mode:
                from resolve_srt import do_render_resolve_audio

                LogManager.log("正在渲染达芬奇时间线音频...")
                self.video_path, project_name, timeline_name = do_render_resolve_audio()
                if not self.video_path:
                    LogManager.log("音频渲染失败")
                    return
            if not self.output_path:
                if self.is_resolve_mode:
                    self.output_path = os.path.join(
                        get_temp_path(),
                        f"{project_name}_{timeline_name}_subtitles_{int(time.time())}.srt",
                    )
                else:
                    self.output_path = (
                        os.path.splitext(self.video_path)[0] + "_subtitles.srt"
                    )

            self.update_output_path.emit(self.output_path)
            do_task(
                self.video_path,
                self.output_path,
                self.ref_path,
                type=self.audio_type,
                model_name=self.model_name,
            )
            self.finished.emit(self.output_path)
        except Exception as e:
            trace = traceback.format_exc()
            self.error.emit(f"{str(e)}\n{trace}")
        finally:
            clear_audio_temp_dir()


class DragDropTextEdit(QTextEdit):
    """支持拖拽的文本编辑框"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        """拖拽进入事件"""
        if event.mimeData().hasUrls():
            event.acceptProposedAction()

    def dropEvent(self, event):
        """拖拽放下事件"""
        urls = event.mimeData().urls()
        if urls:
            file_path = urls[0].toLocalFile()
            if file_path.endswith(".txt"):
                try:
                    with open(file_path, "r", encoding="utf-8") as f:
                        content = f.read()
                    self.setPlainText(content)
                except Exception as e:
                    LogManager.log(f"读取文件失败：{str(e)}")
            else:
                LogManager.log("只支持拖入txt文本文件")


class MainWindow(QMainWindow):
    hotkey_agent = None
    settings_loading = False

    def __init__(self):
        super().__init__()
        self.app_config = AppConfig()
        self.setWindowTitle("文案处理工具")
        self.resize(800, 800)  # 增加窗口高度

        # 创建主widget
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        main_layout = QVBoxLayout(main_widget)

        # 创建分割器
        splitter = QSplitter(Qt.Vertical)
        main_layout.addWidget(splitter)

        # 上半部分：标签页
        top_widget = QWidget()
        top_layout = QVBoxLayout(top_widget)
        tabs = QTabWidget()
        top_layout.addWidget(tabs)
        splitter.addWidget(top_widget)

        # 下半部分：日志输出
        self.log_widget = LogWidget()
        splitter.addWidget(self.log_widget)

        # 设置分割器比例
        splitter.setStretchFactor(0, 4)  # 上半部分占4
        splitter.setStretchFactor(1, 1)  # 下半部分占1

        # 初始化工作线程为None
        self.youhua_worker = None
        self.capcut_worker = None  # 添加 CapCut 导出工作线程
        self.check_worker = None  # 添加校验工作线程
        self.subtitle_worker = None  # 添加字幕生成工作线程
        self.hotkey_agent = None  # 添加热键代理

        # 添加标签页
        tabs.addTab(self.create_youhua_tab(), "文案优化")
        tabs.addTab(self.create_split_tab(), "文案分割")
        tabs.addTab(self.create_capcut_tab(), "CapCut 字幕")
        tabs.addTab(self.create_capcut_check_tab(), "CapCut 字幕校验")
        tabs.addTab(self.create_subtitle_tab(), "字幕识别")
        tabs.addTab(self.create_hotkey_tab(), "热键操作")  # 添加热键标签页
        tabs.addTab(self.create_settings_tab(), "设置")  # 添加设置标签页

        # 输出初始日志
        self.log_widget.log("程序启动")
        self.log_widget.log(f"base_dir: {get_base_dir()}")

        # 设置日志管理器
        from log_manager import LogManager

        LogManager.set_log_widget(self.log_widget)
        self.log_queue = multiprocessing.Queue()
        self.log_worker = LogWorker(self.log_queue)
        self.log_worker.start()

    def log(self, message):
        """统一的日志输出接口"""
        self.log_widget.log(message)
        self.statusBar().showMessage(message)

    def create_youhua_tab(self):
        """创建文案优化标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)

        # 输入区域组
        input_group = QGroupBox("输入区域")
        input_layout = QVBoxLayout(input_group)

        # 原始文案输入区
        input_label = QLabel("请输入需要优化的文案：")
        self.input_text = DragDropTextEdit()  # 使用支持拖拽的文本编辑框
        self.input_text.setMinimumHeight(150)  # 设置最小高度
        input_layout.addWidget(input_label)
        input_layout.addWidget(self.input_text)
        layout.addWidget(input_group)

        # 操作按钮组
        button_group = QGroupBox("操作")
        button_layout = QHBoxLayout(button_group)
        button_layout.setSpacing(10)

        # 执行按钮
        self.execute_btn = QPushButton("执行优化")
        self.execute_btn.setFixedHeight(36)
        self.execute_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #4A90E2;
                color: white;
                border-radius: 4px;
                font-size: 14px;
                padding: 0 20px;
            }
            QPushButton:hover {
                background-color: #357ABD;
            }
            QPushButton:pressed {
                background-color: #2E6DA4;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.execute_btn.clicked.connect(self.run_youhua)

        # 保存按钮
        self.save_btn = QPushButton("保存结果")
        self.save_btn.setFixedHeight(36)
        self.save_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #5CB85C;
                color: white;
                border-radius: 4px;
                font-size: 14px;
                padding: 0 20px;
            }
            QPushButton:hover {
                background-color: #449D44;
            }
            QPushButton:pressed {
                background-color: #3D8B3D;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.save_btn.clicked.connect(self.save_youhua_result)
        self.save_btn.setEnabled(False)  # 初始禁用保存按钮

        button_layout.addStretch()
        button_layout.addWidget(self.execute_btn)
        button_layout.addWidget(self.save_btn)
        button_layout.addStretch()
        layout.addWidget(button_group)

        # 输出区域组
        output_group = QGroupBox("优化结果")
        output_layout = QVBoxLayout(output_group)

        # 优化后文案显示区
        output_label = QLabel("优化后的文案将显示在这里：")
        output_label.setStyleSheet("color: #333333; font-size: 13px;")
        self.output_text = QTextEdit()
        self.output_text.setMinimumHeight(200)  # 设置最小高度
        self.output_text.setStyleSheet(
            """
            QTextEdit {
                border: 1px solid #CCCCCC;
                border-radius: 4px;
                padding: 8px;
                background-color: #F9F9F9;
            }
        """
        )
        output_layout.addWidget(output_label)
        output_layout.addWidget(self.output_text)
        layout.addWidget(output_group)

        # 结果文件组
        result_group = QGroupBox("保存的文件")
        result_layout = QVBoxLayout(result_group)

        # 提示信息
        tip_label = QLabel("提示：保存后可以直接拖拽文件图标到其他应用打开")
        tip_label.setStyleSheet("color: #666666; font-size: 12px;")
        result_layout.addWidget(tip_label)

        # 文件图标区域
        self.youhua_result_layout = QHBoxLayout()
        self.youhua_result_layout.setAlignment(Qt.AlignLeft)
        self.youhua_result_layout.setSpacing(20)  # 增加图标之间的间距
        result_layout.addLayout(self.youhua_result_layout)
        layout.addWidget(result_group)
        # 添加伸缩项
        layout.addStretch()

        return widget

    def create_split_tab(self):
        """创建文案分割标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)

        # 输入设置组
        input_group = QGroupBox("输入设置")
        input_layout = QVBoxLayout(input_group)

        # 原文件选择
        original_layout = QHBoxLayout()
        original_label = QLabel("原文件:")
        original_label.setFixedWidth(60)
        self.original_file = QLineEdit()
        browse_btn = QPushButton("浏览")
        browse_btn.setFixedWidth(80)
        browse_btn.clicked.connect(lambda: self.browse_file(self.original_file))
        original_layout.addWidget(original_label)
        original_layout.addWidget(self.original_file)
        original_layout.addWidget(browse_btn)
        input_layout.addLayout(original_layout)

        layout.addWidget(input_group)

        # 分割设置组
        split_group = QGroupBox("分割设置")
        split_layout = QVBoxLayout(split_group)

        # 最大长度设置
        length_layout = QHBoxLayout()
        length_label = QLabel("最大长度:")
        length_label.setFixedWidth(60)
        self.max_length = QSpinBox()
        self.max_length.setRange(100, 1000)
        self.max_length.setValue(500)
        self.max_length.setFixedWidth(100)
        length_layout.addWidget(length_label)
        length_layout.addWidget(self.max_length)
        length_layout.addStretch()
        split_layout.addLayout(length_layout)

        # 时间间隔设置
        time_layout = QHBoxLayout()
        time_label = QLabel("时间间隔:")
        time_label.setFixedWidth(60)
        self.time_gap = QSpinBox()
        self.time_gap.setRange(0, 60)
        self.time_gap.setValue(0)
        self.time_gap.setFixedWidth(100)
        time_layout.addWidget(time_label)
        time_layout.addWidget(self.time_gap)
        time_layout.addStretch()
        split_layout.addLayout(time_layout)

        layout.addWidget(split_group)

        # 执行按钮
        self.split_btn = QPushButton("执行分割")
        self.split_btn.setFixedHeight(40)
        self.split_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #4A90E2;
                color: white;
                border-radius: 4px;
                font-size: 14px;
            }
            QPushButton:hover {
                background-color: #357ABD;
            }
            QPushButton:pressed {
                background-color: #2E6DA4;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.split_btn.clicked.connect(self.run_split)
        layout.addWidget(self.split_btn)

        # 结果显示组
        result_group = QGroupBox("分割结果")
        result_layout = QVBoxLayout(result_group)

        # 提示信息
        tip_label = QLabel("提示：分割完成后，可以直接拖拽文件图标到其他应用")
        tip_label.setStyleSheet("color: #666666;")
        result_layout.addWidget(tip_label)

        # 结果文件区域
        self.result_layout = QHBoxLayout()
        self.result_layout.setAlignment(Qt.AlignLeft)
        result_layout.addLayout(self.result_layout)

        layout.addWidget(result_group)

        # 添加伸缩项
        layout.addStretch()

        return widget

    def create_capcut_tab(self):
        """创建CapCut字幕标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)

        # 项目选择组
        project_group = QGroupBox("项目选择")
        project_layout = QVBoxLayout(project_group)

        # 项目列表
        self.projects_list = QComboBox()
        self.refresh_projects()

        # 刷新按钮
        refresh_btn = QPushButton("刷新项目列表")
        refresh_btn.clicked.connect(self.refresh_projects)

        project_layout.addWidget(self.projects_list)
        project_layout.addWidget(refresh_btn)
        layout.addWidget(project_group)

        # 导出设置组
        export_group = QGroupBox("导出设置")
        export_layout = QVBoxLayout(export_group)

        # 存储路径选择
        path_layout = QHBoxLayout()
        path_label = QLabel("存储路径:")
        path_label.setFixedWidth(60)
        self.save_path = QLineEdit()
        self.save_path.setText(os.path.expanduser("~/Desktop"))
        browse_btn = QPushButton("浏览")
        browse_btn.setFixedWidth(80)
        browse_btn.clicked.connect(lambda: self.browse_directory(self.save_path))
        path_layout.addWidget(path_label)
        path_layout.addWidget(self.save_path)
        path_layout.addWidget(browse_btn)
        export_layout.addLayout(path_layout)

        # 导出类型选择
        type_layout = QHBoxLayout()
        type_label = QLabel("导出类型:")
        type_label.setFixedWidth(60)
        self.export_type = QComboBox()
        self.export_type.addItems(["srt", "txt"])
        self.export_type.setFixedWidth(100)
        type_layout.addWidget(type_label)
        type_layout.addWidget(self.export_type)
        type_layout.addStretch()
        export_layout.addLayout(type_layout)

        layout.addWidget(export_group)

        # 导出按钮
        self.export_btn = QPushButton("导出")
        self.export_btn.setFixedHeight(40)
        self.export_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #4A90E2;
                color: white;
                border-radius: 4px;
                font-size: 14px;
            }
            QPushButton:hover {
                background-color: #357ABD;
            }
            QPushButton:pressed {
                background-color: #2E6DA4;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.export_btn.clicked.connect(self.run_export)
        layout.addWidget(self.export_btn)

        # 添加伸缩项
        layout.addStretch()

        return widget

    def create_capcut_check_tab(self):
        """创建CapCut字幕校验标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)

        # 项目选择组
        project_group = QGroupBox("项目选择")
        project_layout = QVBoxLayout(project_group)

        # 项目列表
        self.check_projects_list = QComboBox()
        self.refresh_check_projects()  # 初始化项目列表

        # 刷新按钮
        refresh_btn = QPushButton("刷新项目列表")
        refresh_btn.clicked.connect(self.refresh_check_projects)

        project_layout.addWidget(self.check_projects_list)
        project_layout.addWidget(refresh_btn)
        layout.addWidget(project_group)

        # 参考文本文件选择（可选）
        ref_group = QGroupBox("参考文本（可选）")
        ref_layout = QHBoxLayout(ref_group)
        self.ref_file = QLineEdit()
        ref_browse_btn = QPushButton("浏览")
        ref_browse_btn.setFixedWidth(80)
        ref_browse_btn.clicked.connect(lambda: self.browse_file(self.ref_file))
        ref_layout.addWidget(self.ref_file)
        ref_layout.addWidget(ref_browse_btn)
        layout.addWidget(ref_group)

        # 存储路径选择
        save_group = QGroupBox("保存设置")
        save_layout = QHBoxLayout(save_group)
        self.check_save_path = QLineEdit()
        self.check_save_path.setText(os.path.expanduser("~/Downloads"))
        save_browse_btn = QPushButton("浏览")
        save_browse_btn.setFixedWidth(80)
        save_browse_btn.clicked.connect(
            lambda: self.browse_directory(self.check_save_path)
        )
        save_layout.addWidget(self.check_save_path)
        save_layout.addWidget(save_browse_btn)
        layout.addWidget(save_group)

        # 执行按钮
        self.check_btn = QPushButton("执行校验")  # 保存按钮引用
        self.check_btn.setFixedHeight(40)
        self.check_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #4A90E2;
                color: white;
                border-radius: 4px;
                font-size: 14px;
            }
            QPushButton:hover {
                background-color: #357ABD;
            }
            QPushButton:pressed {
                background-color: #2E6DA4;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.check_btn.clicked.connect(self.run_capcut_check)
        layout.addWidget(self.check_btn)

        # 添加伸缩项
        layout.addStretch()

        return widget

    def audio_type_change(self):
        self.whisper_model.clear()
        audio_type = self.type_model.currentText()
        if audio_type == "groq":
            self.whisper_model.addItems(["whisper-large-v3-turbo", "whisper-large-v3"])
            self.whisper_model.setCurrentText("whisper-large-v3-turbo")
        elif audio_type == "local":
            self.whisper_model.addItems(["tiny", "base", "small", "medium", "large"])
            self.whisper_model.setCurrentText("small")  # 默认选择 small 模型

    def create_subtitle_tab(self):
        """创建字幕识别标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)

        # 输入设置组
        input_group = QGroupBox("输入设置")
        input_layout = QVBoxLayout(input_group)

        # 添加选择模式
        mode_layout = QHBoxLayout()
        self.use_resolve = QCheckBox("使用达芬奇时间线")
        self.use_resolve.setToolTip("选中后将自动渲染达芬奇当前时间线的音频并识别字幕")
        self.use_resolve.stateChanged.connect(self.on_resolve_mode_changed)
        mode_layout.addWidget(self.use_resolve)
        mode_layout.addStretch()
        input_layout.addLayout(mode_layout)

        # 视频文件选择
        video_layout = QHBoxLayout()
        video_label = QLabel("视频文件:")
        video_label.setFixedWidth(60)
        self.video_file = QLineEdit()
        self.video_browse_btn = QPushButton("浏览")
        self.video_browse_btn.setFixedWidth(80)
        self.video_browse_btn.clicked.connect(lambda: self.browse_file(self.video_file))
        video_layout.addWidget(video_label)
        video_layout.addWidget(self.video_file)
        video_layout.addWidget(self.video_browse_btn)
        input_layout.addLayout(video_layout)

        # 参考文本文件选择（可选）
        ref_layout = QHBoxLayout()
        ref_label = QLabel("参考文本:")
        ref_label.setFixedWidth(60)
        self.subtitle_ref_file = QLineEdit()
        ref_browse_btn = QPushButton("浏览")
        ref_browse_btn.setFixedWidth(80)
        ref_browse_btn.clicked.connect(lambda: self.browse_file(self.subtitle_ref_file))
        ref_layout.addWidget(ref_label)
        ref_layout.addWidget(self.subtitle_ref_file)
        ref_layout.addWidget(ref_browse_btn)
        input_layout.addLayout(ref_layout)

        # 类型选择
        type_layout = QHBoxLayout()
        type_label = QLabel("模型选择:")
        type_label.setFixedWidth(60)
        self.type_model = QComboBox()
        self.type_model.addItems(["local", "groq"])
        self.type_model.setCurrentText("local")  # 默认选择 small 模型
        self.type_model.setFixedWidth(120)
        type_layout.addWidget(type_label)
        type_layout.addWidget(self.type_model)
        type_layout.addStretch()
        input_layout.addLayout(type_layout)
        self.type_model.currentTextChanged.connect(self.audio_type_change)

        # 模型选择
        model_layout = QHBoxLayout()
        model_label = QLabel("模型选择:")
        model_label.setFixedWidth(60)
        self.whisper_model = QComboBox()
        self.whisper_model.setFixedWidth(120)
        model_layout.addWidget(model_label)
        model_layout.addWidget(self.whisper_model)
        model_layout.addStretch()
        input_layout.addLayout(model_layout)

        layout.addWidget(input_group)
        self.audio_type_change()

        # 输出设置组
        output_group = QGroupBox("输出设置")
        output_layout = QVBoxLayout(output_group)

        # 输出文件选择
        output_layout_h = QHBoxLayout()
        output_label = QLabel("输出文件:")
        output_label.setFixedWidth(60)
        self.subtitle_output_file = QLineEdit()
        output_browse_btn = QPushButton("浏览")
        output_browse_btn.setFixedWidth(80)
        output_browse_btn.clicked.connect(
            lambda: self.save_file_dialog(self.subtitle_output_file, "字幕文件 (*.srt)")
        )
        output_layout_h.addWidget(output_label)
        output_layout_h.addWidget(self.subtitle_output_file)
        output_layout_h.addWidget(output_browse_btn)
        output_layout.addLayout(output_layout_h)

        layout.addWidget(output_group)

        # 执行按钮
        self.subtitle_btn = QPushButton("生成字幕")
        self.subtitle_btn.setFixedHeight(40)
        self.subtitle_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #4A90E2;
                color: white;
                border-radius: 4px;
                font-size: 14px;
            }
            QPushButton:hover {
                background-color: #357ABD;
            }
            QPushButton:pressed {
                background-color: #2E6DA4;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
            """
        )
        self.subtitle_btn.clicked.connect(self.run_subtitle)
        layout.addWidget(self.subtitle_btn)

        # 结果显示组
        result_group = QGroupBox("生成结果")
        result_layout = QVBoxLayout(result_group)

        # 提示信息
        tip_label = QLabel("提示：生成完成后，可以直接拖拽文件图标到其他应用")
        tip_label.setStyleSheet("color: #666666;")
        result_layout.addWidget(tip_label)

        # 结果文件区域
        self.subtitle_result_layout = QHBoxLayout()
        self.subtitle_result_layout.setAlignment(Qt.AlignLeft)
        result_layout.addLayout(self.subtitle_result_layout)

        # 添加到达芬奇按钮
        self.add_to_resolve_btn = QPushButton("添加到达芬奇时间线")
        self.add_to_resolve_btn.setFixedHeight(40)
        self.add_to_resolve_btn.setEnabled(False)  # 初始禁用
        self.add_to_resolve_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #5CB85C;
                color: white;
                border-radius: 4px;
                font-size: 14px;
            }
            QPushButton:hover {
                background-color: #449D44;
            }
            QPushButton:pressed {
                background-color: #3D8B3D;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
            """
        )
        self.add_to_resolve_btn.clicked.connect(self.add_subtitle_to_resolve)
        result_layout.addWidget(self.add_to_resolve_btn)

        layout.addWidget(result_group)

        # 添加伸缩项
        layout.addStretch()

        return widget

    def create_hotkey_tab(self):
        """创建热键标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)

        # 类型选择组
        type_group = QGroupBox("操作类型")
        type_layout = QVBoxLayout(type_group)

        # 类型选择下拉框
        self.hotkey_type = QComboBox()
        self.hotkey_type.addItems(
            [
                "move_clip - 移动片段",
                "remove_subtitle_gaps - 移除字幕间隙",
                "remove_frame - 抽帧",
                "interpolation_frame - 补帧",
            ]
        )
        type_layout.addWidget(self.hotkey_type)
        layout.addWidget(type_group)

        # 控制按钮组
        control_group = QGroupBox("控制")
        control_layout = QHBoxLayout(control_group)

        # 开始按钮
        self.start_hotkey_btn = QPushButton("开始")
        self.start_hotkey_btn.setFixedHeight(40)
        self.start_hotkey_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #4A90E2;
                color: white;
                border-radius: 4px;
                font-size: 14px;
                padding: 0 20px;
            }
            QPushButton:hover {
                background-color: #357ABD;
            }
            QPushButton:pressed {
                background-color: #2E6DA4;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.start_hotkey_btn.clicked.connect(self.start_hotkey)

        # 停止按钮
        self.stop_hotkey_btn = QPushButton("停止")
        self.stop_hotkey_btn.setFixedHeight(40)
        self.stop_hotkey_btn.setEnabled(False)
        self.stop_hotkey_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #D9534F;
                color: white;
                border-radius: 4px;
                font-size: 14px;
                padding: 0 20px;
            }
            QPushButton:hover {
                background-color: #C9302C;
            }
            QPushButton:pressed {
                background-color: #AC2925;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.stop_hotkey_btn.clicked.connect(self.stop_hotkey)

        control_layout.addWidget(self.start_hotkey_btn)
        control_layout.addWidget(self.stop_hotkey_btn)
        layout.addWidget(control_group)

        # 说明信息组
        info_group = QGroupBox("使用说明")
        info_layout = QVBoxLayout(info_group)
        info_text = QLabel(
            """
        1. 选择需要执行的操作类型
        2. 点击"开始"按钮启动监听
        3. 按 ~ 键开始执行选定的操作
        4. 按 F1 键停止当前操作
        5. 点击"停止"按钮结束监听
        """
        )
        info_text.setWordWrap(True)
        info_layout.addWidget(info_text)
        layout.addWidget(info_group)

        # 添加伸缩项
        layout.addStretch()

        return widget

    def load_multi_config_keys(self):
        multi_config_keys = self.app_config["multi_config_keys"]
        self.config_name.clear()
        for key in multi_config_keys:
            self.config_name.addItem(key)

    def save_multi_config(self):
        """保存多配置"""
        name = self.config_name.currentText()
        if not name:
            QMessageBox.warning(self, "错误", "请选择或输入一个配置名称")
            return
        self.app_config.save_multi_config(name)
        self.load_multi_config_keys()
        LogManager.log("保存成功")

    def del_multi_config(self):
        """删除多配置"""
        name = self.config_name.currentText()
        multi_config_keys = self.app_config["multi_config_keys"]
        if not name:
            QMessageBox.warning(self, "错误", "请选择或输入一个配置名称")
            return
        if name not in multi_config_keys:
            QMessageBox.warning(self, "错误", "该配置不存在")
        if self.app_config.del_multi_config(name):
            self.load_multi_config_keys()
            LogManager.log("删除成功")

    def load_multi_config(self):
        """加载多配置"""
        print("load_multi_config  ---------")
        name = self.config_name.currentText()
        multi_config_keys = self.app_config["multi_config_keys"]
        if not name:
            QMessageBox.warning(self, "错误", "请选择或输入一个配置名称")
            return
        if name not in multi_config_keys:
            QMessageBox.warning(self, "错误", "该配置不存在")
            return
        if self.app_config.load_multi_config(name):
            self.load_settings()
            LogManager.log("加载成功")

    def create_settings_tab(self):
        """创建设置标签页"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(20, 20, 20, 20)
        layout.setSpacing(15)

        # 语音识别组
        audio_group = QGroupBox("语音识别设置")
        audio_layout = QFormLayout(audio_group)
        audio_layout.setContentsMargins(25, 30, 25, 25)  # 增加内边距
        audio_layout.setSpacing(20)  # 增加间距
        audio_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        audio_layout.setLabelAlignment(Qt.AlignRight)

        # API Key 输入框
        self.groq_api_key = QLineEdit()
        self.groq_api_key.setPlaceholderText("Groq API Key")
        self.groq_api_key.setEchoMode(QLineEdit.Password)
        self.groq_api_key.setMinimumWidth(400)  # 增加最小宽度
        self.groq_api_key.textChanged.connect(self.save_settings)  # 添加自动保存
        audio_layout.addRow(self.create_label("Groq API Key:"), self.groq_api_key)
        layout.addWidget(audio_group)

        # API 设置组
        api_group = QGroupBox("API 设置")
        api_layout = QFormLayout(api_group)
        api_layout.setContentsMargins(25, 30, 25, 25)  # 增加内边距
        api_layout.setSpacing(20)  # 增加间距
        api_layout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        api_layout.setLabelAlignment(Qt.AlignRight)

        # Base URL 输入框
        self.base_url = QLineEdit()
        self.base_url.setPlaceholderText("请输入 API 基础 URL")
        self.base_url.setMinimumWidth(400)  # 增加最小宽度
        self.base_url.textChanged.connect(self.save_settings)  # 添加自动保存
        api_layout.addRow(self.create_label("Base URL:"), self.base_url)

        # API Key 输入框
        self.api_key = QLineEdit()
        self.api_key.setPlaceholderText("请输入 API Key")
        self.api_key.setEchoMode(QLineEdit.Password)
        self.api_key.setMinimumWidth(400)  # 增加最小宽度
        self.api_key.textChanged.connect(self.save_settings)  # 添加自动保存
        api_layout.addRow(self.create_label("API Key:"), self.api_key)

        # Model 输入框
        self.model = QLineEdit()
        self.model.setPlaceholderText("请输入模型名称")
        self.model.setMinimumWidth(400)  # 增加最小宽度
        self.model.textChanged.connect(self.save_settings)  # 添加自动保存
        api_layout.addRow(self.create_label("Model:"), self.model)

        layout.addWidget(api_group)

        # 提示信息
        tip_label = QLabel("提示：设置内容会自动保存")
        tip_label.setStyleSheet("color: #666666; font-size: 12px;")
        tip_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(tip_label)

        # 多配置组
        multi_config_group = QGroupBox("预设")
        multi_config_layout = QVBoxLayout(multi_config_group)

        # 类型选择下拉框
        self.config_name = QComboBox()
        self.config_name.setEditable(True)
        self.load_multi_config_keys()
        multi_config_layout.addWidget(self.config_name)
        multi_config_button_layout = QHBoxLayout()
        multi_config_layout.addLayout(multi_config_button_layout)

        self.save_config_btn = QPushButton("保存")
        self.save_config_btn.setFixedHeight(40)
        self.save_config_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #4A90E2;
                color: white;
                border-radius: 4px;
                font-size: 14px;
                padding: 0 20px;
            }
            QPushButton:hover {
                background-color: #357ABD;
            }
            QPushButton:pressed {
                background-color: #2E6DA4;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.save_config_btn.clicked.connect(self.save_multi_config)

        self.load_config_btn = QPushButton("加载")
        self.load_config_btn.setFixedHeight(40)
        # self.load_config_btn.setEnabled(False)
        self.load_config_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #5CB85C;
                color: white;
                border-radius: 4px;
                font-size: 14px;
                padding: 0 20px;
            }
              QPushButton:hover {
                background-color: #449D44;
            }
            QPushButton:pressed {
                background-color: #3D8B3D;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.load_config_btn.clicked.connect(self.load_multi_config)

        self.del_config_btn = QPushButton("删除")
        self.del_config_btn.setFixedHeight(40)
        self.del_config_btn.setStyleSheet(
            """
            QPushButton {
                background-color: #D9534F;
                color: white;
                border-radius: 4px;
                font-size: 14px;
                padding: 0 20px;
            }
            QPushButton:hover {
                background-color: #C9302C;
            }
            QPushButton:pressed {
                background-color: #AC2925;
            }
            QPushButton:disabled {
                background-color: #CCCCCC;
            }
        """
        )
        self.del_config_btn.clicked.connect(self.del_multi_config)

        multi_config_button_layout.addWidget(self.save_config_btn)
        multi_config_button_layout.addWidget(self.load_config_btn)
        multi_config_button_layout.addWidget(self.del_config_btn)

        layout.addWidget(multi_config_group)

        # 加载当前配置
        self.load_settings()

        # 添加伸缩项
        layout.addStretch()

        return widget

    def create_label(self, text):
        """创建统一样式的标签"""
        label = QLabel(text)
        label.setStyleSheet(
            """
            QLabel {
                font-size: 14px;  # 增加字体大小
                min-width: 100px;  # 增加标签宽度
                padding-right: 15px;  # 增加右边距
            }
        """
        )
        return label

    def load_settings(self):
        """加载当前配置"""
        self.settings_loading = True
        try:
            self.groq_api_key.setText(self.app_config["groq_api_key"])
            self.api_key.setText(self.app_config["api_key"])
            self.base_url.setText(self.app_config["base_url"])
            self.model.setText(self.app_config["model"])
        except Exception as e:
            self.log(f"加载配置失败：{str(e)}")
        self.settings_loading = False

    def save_settings(self):
        """保存配置"""
        if self.settings_loading:
            return
        try:
            # 获取当前输入值
            base_url = self.base_url.text().strip()
            api_key = self.api_key.text().strip()
            groq_api_key = self.groq_api_key.text().strip()
            model = self.model.text().strip()

            # 只有当所有必填字段都有值时才保存
            if base_url and api_key and model:
                self.app_config["api_key"] = api_key
                self.app_config["groq_api_key"] = groq_api_key
                self.app_config["base_url"] = base_url
                self.app_config["model"] = model

                # 保存到配置文件
                self.app_config.save_config()
                self.log("配置已自动保存")
        except Exception as e:
            self.log(f"保存配置失败：{str(e)}")
            self.show_error(f"保存失败：{str(e)}")

    def show_error(self, message):
        """显示错误消息"""
        from PySide6.QtWidgets import QMessageBox

        QMessageBox.warning(self, "错误", message, QMessageBox.Ok)

    def browse_file(self, line_edit):
        """文件选择对话框"""
        file_name, _ = QFileDialog.getOpenFileName(self, "选择文件")
        if file_name:
            line_edit.setText(file_name)

    def browse_directory(self, line_edit):
        """目录选择对话框"""
        directory = QFileDialog.getExistingDirectory(self, "选择目录")
        if directory:
            line_edit.setText(directory)

    def refresh_projects(self):
        """刷新剪映项目列表"""
        self.projects_list.clear()
        path = os.path.expanduser(
            "~/Movies/CapCut/User Data/Projects/com.lveditor.draft"
        )
        path = Path(path)
        if path.exists():
            # 获取所有项目并按修改时间排序
            projects = []
            for p in path.iterdir():
                draft_file = p / "draft_info.json"
                if draft_file.exists():
                    projects.append(
                        {"path": p, "name": p.name, "mtime": draft_file.stat().st_mtime}
                    )

            # 按修改时间倒序排序
            projects.sort(key=lambda x: x["mtime"], reverse=True)

            # 添加到下拉列表
            for project in projects:
                self.projects_list.addItem(project["name"], project["path"])

            # 自动选择第一个（最新的）项目
            if self.projects_list.count() > 0:
                self.projects_list.setCurrentIndex(0)

    def refresh_check_projects(self):
        """刷新字幕校验标签页的项目列表"""
        self.check_projects_list.clear()
        path = os.path.expanduser(
            "~/Movies/CapCut/User Data/Projects/com.lveditor.draft"
        )
        path = Path(path)
        if path.exists():
            # 获取所有项目并按修改时间排序
            projects = []
            for p in path.iterdir():
                draft_file = p / "draft_info.json"
                if draft_file.exists():
                    projects.append(
                        {"path": p, "name": p.name, "mtime": draft_file.stat().st_mtime}
                    )

            # 按修改时间倒序排序
            projects.sort(key=lambda x: x["mtime"], reverse=True)

            # 添加到下拉列表
            for project in projects:
                self.check_projects_list.addItem(project["name"], project["path"])

            # 自动选择第一个（最新的）项目
            if self.check_projects_list.count() > 0:
                self.check_projects_list.setCurrentIndex(0)

    def run_youhua(self):
        """执行文案优化"""
        try:
            text = self.input_text.toPlainText()
            if not text:
                self.log("请输入原始文案")
                return

            # 禁用执行按钮和输入框
            self.execute_btn.setEnabled(False)
            self.input_text.setEnabled(False)
            self.output_text.clear()
            self.log("正在优化文案...")

            # 创建并启动工作线程
            self.youhua_worker = YouhuaWorker(text)
            self.youhua_worker.finished.connect(self.on_youhua_finished)
            self.youhua_worker.error.connect(self.on_youhua_error)
            self.youhua_worker.start()
        except Exception as e:
            self.log(f"启动优化任务失败：{str(e)}")
            self.execute_btn.setEnabled(True)
            self.input_text.setEnabled(True)

    def on_youhua_finished(self, content):
        """优化完成的回调"""
        try:
            self.output_text.setPlainText(content)
            self.log("文案优化完成")
            self.execute_btn.setEnabled(True)
            self.input_text.setEnabled(True)
            self.save_btn.setEnabled(True)
            self.youhua_worker = None
        except Exception as e:
            self.log(f"显示优化结果失败：{str(e)}")
            self.execute_btn.setEnabled(True)
            self.input_text.setEnabled(True)

    def on_youhua_error(self, error_msg):
        """优化出错的回调"""
        try:
            self.log(f"错误：{error_msg}")
            self.output_text.setPlainText(f"错误：{error_msg}")
            self.execute_btn.setEnabled(True)
            self.input_text.setEnabled(True)
            self.save_btn.setEnabled(False)
            self.youhua_worker = None
        except Exception as e:
            self.log(f"处理错误信息失败：{str(e)}")
            self.execute_btn.setEnabled(True)
            self.input_text.setEnabled(True)

    def run_split(self):
        """执行文案分割"""
        try:
            input_file = self.original_file.text()
            if not input_file or not os.path.exists(input_file):
                self.log("请选择有效的输入文件")
                return

            self.log("正在分割文案...")
            max_length = self.max_length.value()
            time_gap = self.time_gap.value()
            filename, _ = os.path.splitext(input_file)
            current_time = int(time.time())
            output_file = f"{filename}_{current_time}.srt"

            current_time = timedelta(hours=0, minutes=0, seconds=0, milliseconds=0)
            with open(output_file, "w", encoding="utf-8") as f:
                index = 0
                for split in split_text_by_max_length(input_file, max_length):
                    if isinstance(split, OriginalVideo):
                        current_time += timedelta(seconds=time_gap)
                        continue
                    index += 1
                    text_length = len(split)
                    time_length = text_length * 200
                    start_time_str = format_time(current_time)
                    current_time += timedelta(milliseconds=time_length)
                    end_time_str = format_time(current_time)
                    context = f"{index}\n{start_time_str} --> {end_time_str}\n"
                    f.write(context)
                    f.write(split)
                    f.write("\n\n")

            self.log(f"分割完成，已保存到：{output_file}")

            # 清除旧的图标（如果有）
            for i in reversed(range(self.result_layout.count())):
                widget = self.result_layout.itemAt(i).widget()
                if widget:
                    widget.deleteLater()

            # 创建图标
            icon = DraggableLabel(output_file)
            icon.setFixedSize(32, 32)
            self.result_layout.addWidget(icon)

            # 添加文件名标签
            name_label = QLabel(os.path.basename(output_file))
            name_label.setStyleSheet("color: #333333;")
            self.result_layout.addWidget(name_label)

        except Exception as e:
            self.log(f"分割失败：{str(e)}")

    def run_export(self):
        """执行字幕导出"""
        try:
            save_path = self.save_path.text()
            export_type = self.export_type.currentText()

            if not save_path or not os.path.exists(save_path):
                self.log("请选择有效的保存路径")
                return

            # 获取选中的项目
            project_data = self.projects_list.currentData()
            if not project_data:
                self.log("请选择要导出的项目")
                return

            # 禁用导出按钮
            self.export_btn.setEnabled(False)
            self.log("正在导出字幕...")

            # 创建并启动工作线程
            self.capcut_worker = CapcutExportWorker(
                project_data, save_path, export_type
            )
            self.capcut_worker.finished.connect(self.on_export_finished)
            self.capcut_worker.error.connect(self.on_export_error)
            self.capcut_worker.start()

        except Exception as e:
            self.log(f"错误：{str(e)}")
            self.export_btn.setEnabled(True)
            self.capcut_worker = None

    def on_export_finished(self, result):
        """导出完成的回调"""
        if result:
            self.log(f"导出成功：{', '.join(result)}")
        else:
            self.log("导出失败")
        self.export_btn.setEnabled(True)
        self.capcut_worker = None

    def on_export_error(self, error_msg):
        """导出出错的回调"""
        self.log(f"错误：{error_msg}")
        self.export_btn.setEnabled(True)
        self.capcut_worker = None

    def save_youhua_result(self):
        """保存优化结果到文件"""
        try:
            content = self.output_text.toPlainText()
            original_text = self.input_text.toPlainText()
            if not content:
                self.log("没有可保存的内容")
                return

            file_name, _ = QFileDialog.getSaveFileName(
                self,
                "保存文件",
                os.path.expanduser("~/Desktop/优化文案.txt"),
                "文本文件 (*.txt);;所有文件 (*.*)",
            )

            if file_name:
                original_file = os.path.splitext(file_name)[0] + "_original.txt"
                with open(original_file, "w", encoding="utf-8") as f:
                    f.write(original_text)
                with open(file_name, "w", encoding="utf-8") as f:
                    f.write(content)
                self.log(f"文件已保存到：{file_name}")

                # 清除旧的图标（如果有）
                for i in reversed(range(self.youhua_result_layout.count())):
                    widget = self.youhua_result_layout.itemAt(i).widget()
                    if widget:
                        widget.deleteLater()

                # 创建原始文案图标
                original_icon = DraggableLabel(original_file)
                original_icon.setFixedSize(32, 32)
                self.youhua_result_layout.addWidget(original_icon)

                # 添加原始文案文件名标签
                original_name_label = QLabel("原始文案")
                original_name_label.setStyleSheet("color: #333333;")
                self.youhua_result_layout.addWidget(original_name_label)

                # 添加分隔符
                separator = QLabel("|")
                separator.setStyleSheet("color: #CCCCCC;")
                self.youhua_result_layout.addWidget(separator)

                # 创建优化后文案图标
                optimized_icon = DraggableLabel(file_name)
                optimized_icon.setFixedSize(32, 32)
                self.youhua_result_layout.addWidget(optimized_icon)

                # 添加优化后文案文件名标签
                optimized_name_label = QLabel("优化文案")
                optimized_name_label.setStyleSheet("color: #333333;")
                self.youhua_result_layout.addWidget(optimized_name_label)

                # 自动填写到文案分割的原文件输入框
                self.original_file.setText(file_name)
                self.ref_file.setText(file_name)
                self.subtitle_ref_file.setText(file_name)
        except Exception as e:
            self.log(f"保存失败：{str(e)}")

    def run_capcut_check(self):
        """执行字幕校验"""
        try:
            save_path = self.check_save_path.text()
            ref_path = self.ref_file.text() or None

            if not save_path or not os.path.exists(save_path):
                self.log("请选择有效的保存路径")
                return

            if ref_path and not os.path.exists(ref_path):
                self.log("参考文本文件不存在")
                return

            # 获取选中的项目
            project_data = self.check_projects_list.currentData()
            if not project_data:
                self.log("请选择要校验的项目")
                return

            # 禁用校验按钮
            self.check_btn.setEnabled(False)
            self.log(f"正在处理项目：{project_data.name}")

            # 创建并启动工作线程
            self.check_worker = CapcutCheckWorker(project_data, save_path, ref_path)
            self.check_worker.finished.connect(self.on_check_finished)
            self.check_worker.error.connect(self.on_check_error)
            self.check_worker.start()

        except Exception as e:
            self.log(f"错误：{str(e)}")
            self.check_btn.setEnabled(True)

    def on_check_finished(self, output_file):
        """校验完成的回调"""
        self.log(f"校验完成，结果已保存到：{output_file}")
        self.check_btn.setEnabled(True)
        self.check_worker = None

    def on_check_error(self, error_msg):
        """校验出错的回调"""
        self.log(f"错误：{error_msg}")
        self.check_btn.setEnabled(True)
        self.check_worker = None

    def save_file_dialog(self, line_edit, file_filter):
        """保存文件对话框"""
        file_name, _ = QFileDialog.getSaveFileName(self, "保存文件", "", file_filter)
        if file_name:
            line_edit.setText(file_name)

    def on_resolve_mode_changed(self, state):
        """达芬奇模式切换回调"""
        is_resolve_mode = state != 0
        self.video_file.setEnabled(not is_resolve_mode)
        self.video_browse_btn.setEnabled(not is_resolve_mode)
        if is_resolve_mode:
            self.video_file.setText("使用达芬奇时间线")
        else:
            self.video_file.setText("")

    def run_subtitle(self):
        """执行字幕生成"""
        try:
            # 检查是否使用达芬奇模式
            is_resolve_mode = self.use_resolve.isChecked()
            if is_resolve_mode:
                video_path = ""
            else:
                video_path = self.video_file.text()
                if not video_path or not os.path.exists(video_path):
                    self.log("请选择有效的视频文件")
                    return

            ref_path = self.subtitle_ref_file.text() or None
            output_path = self.subtitle_output_file.text()
            audio_type = self.type_model.currentText()
            model_name = self.whisper_model.currentText()  # 获取选择的模型名称

            if ref_path and not os.path.exists(ref_path):
                self.log("参考文本文件不存在")
                return

            # 禁用生成按钮
            self.subtitle_btn.setEnabled(False)
            self.log("正在生成字幕...")

            # 创建并启动工作线程
            self.subtitle_worker = SubtitleWorker(
                video_path,
                output_path,
                ref_path,
                is_resolve_mode,
                audio_type,
                model_name,
            )
            self.subtitle_worker.finished.connect(self.on_subtitle_finished)
            self.subtitle_worker.error.connect(self.on_subtitle_error)
            self.subtitle_worker.progress.connect(self.log)
            self.subtitle_worker.update_output_path.connect(self.update_output_path)
            self.subtitle_worker.start()

        except Exception as e:
            self.log(f"错误：{str(e)}")
            self.subtitle_btn.setEnabled(True)

    def update_output_path(self, output_file):
        """更新输出文件路径"""
        self.subtitle_output_file.setText(output_file)

    def on_subtitle_finished(self, output_file):
        """字幕生成完成的回调"""
        self.log(f"字幕生成完成，已保存到：{output_file}")
        self.subtitle_btn.setEnabled(True)

        # 清除旧的图标（如果有）
        for i in reversed(range(self.subtitle_result_layout.count())):
            widget = self.subtitle_result_layout.itemAt(i).widget()
            if widget:
                widget.deleteLater()

        # 创建图标
        icon = DraggableLabel(output_file)
        icon.setFixedSize(32, 32)
        self.subtitle_result_layout.addWidget(icon)

        # 添加文件名标签
        name_label = QLabel(os.path.basename(output_file))
        name_label.setStyleSheet("color: #333333;")
        self.subtitle_result_layout.addWidget(name_label)

        # 启用添加到达芬奇按钮
        self.add_to_resolve_btn.setEnabled(True)

        self.subtitle_worker = None

    def on_subtitle_error(self, error_msg):
        """字幕生成出错的回调"""
        self.log(f"错误：{error_msg}")
        self.subtitle_btn.setEnabled(True)
        self.subtitle_worker = None

    def add_subtitle_to_resolve(self):
        """添加字幕到达芬奇时间线"""
        try:
            output_path = self.subtitle_output_file.text()
            if not output_path or not os.path.exists(output_path):
                self.log("请先生成字幕文件")
                return

            self.log("正在添加字幕到达芬奇时间线...")
            self.add_to_resolve_btn.setEnabled(False)

            # 导入 resolve_srt 模块
            from resolve_srt import append_srt_to_timeline

            # 添加字幕到时间线
            if append_srt_to_timeline(output_path):
                self.log("字幕已成功添加到达芬奇时间线")
            else:
                self.log("添加字幕到达芬奇时间线失败")
        except Exception as e:
            self.log(f"错误：{str(e)}")
        finally:
            self.add_to_resolve_btn.setEnabled(True)

    def start_hotkey(self):
        """启动热键监听"""
        try:
            selected_type = self.hotkey_type.currentText().split(" - ")[0]
            process = multiprocessing.Process(
                target=hotkey_agent_start, args=(selected_type, self.log_queue)
            )
            process.daemon = True
            process.start()
            self.hotkey_process = process
            self.start_hotkey_btn.setEnabled(False)
            self.stop_hotkey_btn.setEnabled(True)
            self.hotkey_type.setEnabled(False)

        except Exception as e:
            self.log_widget.log(f"启动热键监听失败: {str(e)}")
            self.stop_hotkey()

    def stop_hotkey(self):
        """停止热键监听"""
        if self.hotkey_process:
            self.hotkey_process.terminate()
            self.hotkey_process = None
        self.start_hotkey_btn.setEnabled(True)
        self.stop_hotkey_btn.setEnabled(False)
        self.hotkey_type.setEnabled(True)


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()
